{$MODE objfpc}

unit PythonClassObject;
  
// Class object interface
// Revealing some structures (not for general use) 

interface
uses PythonTypes;

type
  PyClassObjectPtr = ^PyClassObject;

  PyClassObject = record 
      //PyObject_HEAD
      ob_refcnt: 	Py_ssize_t;
      ob_type: 	PyTypeObjectPtr;
  
      cl_bases: PyObjectPtr;	// A tuple of class objects */
      cl_dict:  PyObjectPtr;	// A dictionary */
      cl_name:  PyObjectPtr;	// A string */
  
      // The following three are functions or NULL */
      cl_getattr: PyObjectPtr;
      cl_setattr: PyObjectPtr;
      cl_delattr: PyObjectPtr;
    end;

  PyInstanceObject = record
      //PyObject_HEAD
      ob_refcnt: 	Py_ssize_t;
      ob_type: 	  PyTypeObjectPtr;

      in_class:   PyClassObjectPtr;	  // The class object */
      in_dict:    PyObjectPtr;	      // A dictionary */
      in_weakreflist: PyObjectPtr;    // List of weak references */
    end;

  PyMethodObject = record
      //PyObject_HEAD
      ob_refcnt: 	Py_ssize_t;
      ob_type: 	  PyTypeObjectPtr;

      im_func:    PyObjectPtr;   // The callable object implementing the method */
      im_self:    PyObjectPtr;   // The instance it is bound to, or NULL */
      im_class:   PyObjectPtr;  // The class that asked for the method */
      im_weakreflist: PyObjectPtr; // List of weak references */
    end;

var 
  PyClass_Type: PyTypeObject; cvar; external;
  PyInstance_Type: PyTypeObject; cvar; external;
  PyMethod_Type: PyTypeObject; cvar; external;

function PyClass_New(o1, o2, o3: PyObjectPtr): PyObjectPtr; cdecl; external;
function PyInstance_New(o1, o2, o3: PyObjectPtr): PyObjectPtr; cdecl; external;
function PyInstance_NewRaw(o1, o2: PyObjectPtr): PyObjectPtr; cdecl; external;
function PyMethod_New(o1, o2, o3: PyObjectPtr): PyObjectPtr; cdecl; external;


function PyMethod_Function(o1: PyObjectPtr): PyObjectPtr; cdecl; external; //BORROWED...
function PyMethod_Self(o1: PyObjectPtr): PyObjectPtr; cdecl; external;
function PyMethod_Class(o1: PyObjectPtr): PyObjectPtr; cdecl; external;

// Look up attribute with name (a string) on instance object pinst, using
 // * only the instance and base class dicts.  If a descriptor is found in
 // * a class dict, the descriptor is returned without calling it.
 // * Returns NULL if nothing found, else a borrowed reference to the
 // * value associated with name in the dict in which name was found.
 // * The point of this routine is that it never calls arbitrary Python
 // * code, so is always "safe":  all it does is dict lookups.  The function
 // * can't fail, never sets an exception, and NULL is not an error (it just
 // * means "not found").
 
function _PyInstance_Lookup(pinst, name: PyObjectPtr): PyObjectPtr; cdecl; external;

function PyClass_IsSubclass(o1, o2: PyObjectPtr): Integer; cdecl; external;



//TODO:
// #define PyClass_Check(op) ((op)->ob_type == &PyClass_Type)
// #define PyInstance_Check(op) ((op)->ob_type == &PyInstance_Type)
// #define PyMethod_Check(op) ((op)->ob_type == &PyMethod_Type)

// Macros for direct access to these values. Type checks are *not*
//   done, so use with care. */
// #define PyMethod_GET_FUNCTION(meth) \
//         (((PyMethodObject *)meth) -> im_func)
// #define PyMethod_GET_SELF(meth) \
//  (((PyMethodObject *)meth) -> im_self)
// #define PyMethod_GET_CLASS(meth) \
//  (((PyMethodObject *)meth) -> im_class)


implementation

end.
